#pragma once
#include <iostream>
#include <functional>
#include <vector>
#include "channel.hpp"
using namespace std;
using work_t = std::function<void()>;

enum
{
    OK = 0,
    USAGEFAIL,
    PIPEFAIL,
    FORKFAIL
};

class processpool
{
public:
    processpool(int num, work_t work) : _num(num), _work(work)
    {
    }
    int InitProcessPool()
    {
        for (int i = 0; i < _num; i++)
        {
            // 先创建管道
            int pipefd[2] = {0};
            int n = pipe(pipefd);
            if (n < 0)
                return PIPEFAIL;

            // 然后创建子进程
            // 父子进程基于管道进行通信，子进程需要读取父进程的指令
            int id = ::fork();
            if (id < 0)
                return FORKFAIL;
            else if (id == 0)
            {
                // 子进程
                ::close(pipefd[1]);
                // 方便后续操作
                dup2(pipefd[0], 0);
                _work();
                exit(OK);
            }
            else
            {
                // 父进程
                ::close(pipefd[0]);
                _channels.emplace_back(pipefd[1], id);
            }
        }
        return OK;
    }
    void detach()
    {
        // 派发总共20个任务
        int task = 5;
        int who = 0;
        while (task--)
        {
            int taskid = ts.select();
            channel &cur = _channels[who++];
            cur.send(taskid);
            who %= _channels.size();
            cout << "进程" << cur.name() << "执行任务：" << taskid << "剩余任务量：" << task << endl;
            sleep(1);
        }
    }
    void DestoryProcessPool()
    {
        for (auto c : _channels)
        {
            ::close(c.wfd());
        }
        for (auto c : _channels)
        {
            ::waitpid(c.who(), nullptr, 0);
        }
    }
    ~processpool()
    {
    }

private:
    std::vector<channel> _channels;
    int _num;
    work_t _work;
};